package com.andy.controller;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.andy.service.ITestService;
import com.andy.utils.CookieUtils;
import com.andy.utils.TestUtils;
import com.andy.vo.CookieVO;
import com.andy.vo.ExamScoreVO;
import com.andy.vo.ExamSubjectVO;
import com.andy.vo.ExamTestVO;
import com.andy.vo.ExamUserVO;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

@Controller
@RequestMapping(value = "/student")
public class TestController {
	
	@Autowired
	private ITestService testService;
	
	@SuppressWarnings("deprecation")
	@RequestMapping(value = "/toTest/{subId}")
	public String toTest(Model model, @PathVariable Integer subId, HttpSession session, HttpServletResponse response, HttpServletRequest request) {
		ExamUserVO user = (ExamUserVO) session.getAttribute("examUser");
		ExamScoreVO scoreVO = testService.getScore(subId, user.getUserId());
		boolean isExists = false;
		long remainingSecond = 0;
		
		ExamSubjectVO sub = testService.getSubjectById(subId);
		if (sub != null) {
			int totalSecond = sub.getTotalTime() * 60;
			if (scoreVO != null) {
				isExists = true;
				Calendar startTime = Calendar.getInstance();
				startTime.setTime(scoreVO.getExamTime());
				
				Calendar currentTime = Calendar.getInstance();
				currentTime.setTime(new Date());
				
				long startSecond = startTime.getTimeInMillis();
				long currentSecond = currentTime.getTimeInMillis();
				remainingSecond = totalSecond - (currentSecond - startSecond) / 1000;
				Cookie multiTestListCookie = CookieUtils.getCookieByName(request, "multiTestList");
				Cookie singleTestListCookie = CookieUtils.getCookieByName(request, "singleTestList");
				Cookie answerListCookie = CookieUtils.getCookieByName(request, "answerList");
				try {
					ObjectMapper mapper = new ObjectMapper();
					model.addAttribute("multiTestList", mapper.readValue(multiTestListCookie.getValue(), List.class));
					model.addAttribute("singleTestList", mapper.readValue(singleTestListCookie.getValue(), List.class));
					model.addAttribute("answerList", answerListCookie.getValue());
				} catch (JsonParseException e) {
					e.printStackTrace();
				} catch (JsonMappingException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
				
			} else {
				Map<Integer, List<ExamTestVO>> resultMap = testService.getTestListBySubject(subId, user.getUserId());
				model.addAttribute("multiTestList", resultMap.get(TestUtils.MULTI_TEST_TYPE));
				model.addAttribute("singleTestList", resultMap.get(TestUtils.SINGLE_TEST_TYPE));
				remainingSecond = totalSecond;
				try {
					ObjectMapper mapper = new ObjectMapper();
					String multiTestListJson = mapper.writeValueAsString(resultMap.get(TestUtils.MULTI_TEST_TYPE));
					String singleTestListJson = mapper.writeValueAsString(resultMap.get(TestUtils.SINGLE_TEST_TYPE));
					addCookie(response, "multiTestList", multiTestListJson);
					addCookie(response, "singleTestList", singleTestListJson);
					addCookie(response, "answerList", "[]");
				} catch (JsonProcessingException e) {
					e.printStackTrace();
				}
			}
		}
		
		model.addAttribute("remainingTime", remainingSecond);
		model.addAttribute("isExists", isExists);
		model.addAttribute("subId", subId);
		return "student/test";
	}
	
	@RequestMapping(value = "/assignment", method = RequestMethod.POST)
	public String assignment(HttpServletRequest request, String userId, Integer subId, Model model, RedirectAttributes redirectAttr) {
		Map<String, String[]> parameterMap = request.getParameterMap();
		Set<Entry<String, String[]>> entrySet = parameterMap.entrySet();
		List<Integer> answerIds = new ArrayList<Integer>();
		Map<String, String[]> testMap = new HashMap<String, String[]>();
		if (entrySet != null) {
			Iterator<Entry<String, String[]>> it = entrySet.iterator();
			final String TEST_PREFIX = "test";
			while (it.hasNext()) {
				Entry<String, String[]> entry = it.next();
				String key = entry.getKey();
				String[] splitArrayString = key.split("_");
				if (splitArrayString.length == 2) {
					if (TEST_PREFIX.equals(splitArrayString[0])) {
						answerIds.add(Integer.valueOf(splitArrayString[1]));
						testMap.put(splitArrayString[1], entry.getValue());
					}
				}
			}
			ExamScoreVO score = testService.calculateScore(answerIds, testMap, userId, subId);
			ExamSubjectVO subjectVO = testService.getSubjectById(subId);
			redirectAttr.addFlashAttribute("score", score);
			redirectAttr.addFlashAttribute("subject", subjectVO);
			return "redirect:/student/subjects";
		}
		return null;
	}
	
	/**
     * 读取所有cookie
     * 注意二、从客户端读取Cookie时，包括maxAge在内的其他属性都是不可读的，也不会被提交。浏览器提交Cookie时只会提交name与value属性。maxAge属性只被浏览器用来判断Cookie是否过期
     * @param request
     * @param response
     */
    @RequestMapping("/showCookies")
    public void showCookies(HttpServletRequest request, HttpServletResponse response ){
         
        Cookie[] cookies = request.getCookies();//这样便可以获取一个cookie数组
        if (null==cookies) {
            System.out.println("没有cookie=========");
        } else {
            for(Cookie cookie : cookies){
                System.out.println("name:" + cookie.getName() + ",value:" +  cookie.getValue());
            }
        }
         
    }
    
    /**
     * 添加cookie
     * @param response
     * @param name
     * @param value
     */
    @RequestMapping("/addCookie")
    public void addCookie(HttpServletResponse response, String name,String value){
        Cookie cookie = new Cookie(name.trim(), value.trim());
        cookie.setMaxAge(90 * 60);// 设置为90min
        cookie.setPath("/");
        System.out.println("已添加===============");
        response.addCookie(cookie);
    }
    
    @SuppressWarnings({ "deprecation" })
	@RequestMapping("/editTestAnswerCookie")
    public void editTestAnswerCookie(HttpServletRequest request, HttpServletResponse response, String name, String value){
    	Map<String, Cookie> cookieMap = CookieUtils.ReadCookieMap(request);
    	ObjectMapper mapper = new ObjectMapper();
    	try {
    		CookieVO cookieVO = mapper.readValue(value, CookieVO.class);
    		JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, CookieVO.class);
    		List<CookieVO> cookieList = mapper.readValue(cookieMap.get(name).getValue(), javaType);
    		List<CookieVO> newCookieList = new ArrayList<CookieVO>();
    		for (CookieVO vo : cookieList) {
    			if (vo.getTestId() != cookieVO.getTestId()) {
    				newCookieList.add(vo);
    			}
    		}
    		newCookieList.add(cookieVO);
    		String cookieValue = mapper.writeValueAsString(newCookieList);
    		editCookie(request, response, name, cookieValue);
		} catch (JsonParseException e) {
			e.printStackTrace();
		} catch (JsonMappingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
        
         
    }
    
    /**
     * 修改cookie
     * @param request
     * @param response
     * @param name
     * @param value
     * 注意一、修改、删除Cookie时，新建的Cookie除value、maxAge之外的所有属性，例如name、path、domain等，都要与原Cookie完全一样。否则，浏览器将视为两个不同的Cookie不予覆盖，导致修改、删除失败。
     */
    @RequestMapping("/editCookie")
    public void editCookie(HttpServletRequest request, HttpServletResponse response, String name, String value){
        Cookie[] cookies = request.getCookies();
        if (null == cookies) {
        	addCookie(response, name, value);
        } else {
            for(Cookie cookie : cookies){
                if(cookie.getName().equals(name)){
                    System.out.println("原值为:" + cookie.getValue());
                    cookie.setValue(value);
                    cookie.setPath("/");
                    cookie.setMaxAge(90 * 60);// 设置为90min
                    System.out.println("被修改的cookie名字为:" + cookie.getName() + ",新值为:" + cookie.getValue());
                    response.addCookie(cookie);
                    break;
                }
            }
        }
         
    }
    
    /**
     * 删除cookie
     * @param request
     * @param response
     * @param name
     */
    @RequestMapping("/delCookie")
    public void delCookie(HttpServletRequest request, HttpServletResponse response, String name){
        Cookie[] cookies = request.getCookies();
        if (null==cookies) {
            System.out.println("没有cookie==============");
        } else {
            for(Cookie cookie : cookies){
                if(cookie.getName().equals(name)){
                    cookie.setValue(null);
                    cookie.setMaxAge(0);// 立即销毁cookie
                    cookie.setPath("/");
                    System.out.println("被删除的cookie名字为:"+cookie.getName());
                    response.addCookie(cookie);
                    break;
                }
            }
        }
    }

}
